﻿using System;

namespace Eniux.SharpOpenGL
{
    /// <summary>
    /// NativeWindow类型渲染上下文
    /// </summary>
    public class NativeWindowRenderContext : RenderContext
    {
        #region 变量

        /// <summary>
        /// window句柄
        /// </summary>
        protected IntPtr windowHandle = IntPtr.Zero;

        #endregion

        #region 构造
		
        /// <summary>
        /// 默认构造
        /// </summary>
        public NativeWindowRenderContext()
        {
            //设置GDI绘制不可用
            GDIDrawingEnabled = false;
        }
 
        #endregion

        #region 重写方法

        /// <summary>
        /// 创建渲染上下文
        /// </summary>
        /// <param name="gl">OpenGL上下文</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="bitDepth">位深</param>
        /// <param name="parameter">参数</param>
        /// <returns>bool</returns>
        public override bool Create(OpenGL gl, int width, int height, int bitDepth, object parameter)
        {
            //  Call the base.
            base.Create(gl, width, height, bitDepth, parameter);

            //  Cast the parameter to the device context.
            try
            {
                windowHandle = (IntPtr)parameter;
            }
            catch
            {
                throw new Exception("A valid Window Handle must be provided for the NativeWindowRenderContextProvider");
            }

            //	Get the window device context.
            deviceContextHandle = Win32.GetDC(windowHandle);

            //	Setup a pixel format.
            Win32.PIXELFORMATDESCRIPTOR pfd = new Win32.PIXELFORMATDESCRIPTOR();
            pfd.Init();
            pfd.nVersion = 1;
            pfd.dwFlags = Win32.PFD_DRAW_TO_WINDOW | Win32.PFD_SUPPORT_OPENGL | Win32.PFD_DOUBLEBUFFER;
            pfd.iPixelType = Win32.PFD_TYPE_RGBA;
            pfd.cColorBits = (byte)bitDepth;
            pfd.cDepthBits = 16;
            pfd.cStencilBits = 8;
            pfd.iLayerType = Win32.PFD_MAIN_PLANE;

            //	Match an appropriate pixel format 
            int iPixelformat;
            if ((iPixelformat = Win32.ChoosePixelFormat(deviceContextHandle, pfd)) == 0)
                return false;

            //	Sets the pixel format
            if (Win32.SetPixelFormat(deviceContextHandle, iPixelformat, pfd) == 0)
            {
                return false;
            }

            //	Create the render context.
            renderContextHandle = Win32.wglCreateContext(deviceContextHandle);

            //  Make the context current.
            MakeCurrent();

            //  Return success.
            return true;
        }

        /// <summary>
        /// 销毁渲染上下文
        /// </summary>
        public override void Destroy()
        {
            //	释放设备上下文
            Win32.ReleaseDC(windowHandle, deviceContextHandle);

            //	Call the base, which will delete the render context handle.
            base.Destroy();
        }

        /// <summary>
        ///设置渲染上下文尺寸.
        /// </summary>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        public override void SetDimensions(int width, int height)
        {
            //  Call the base.
            base.SetDimensions(width, height);
        }

        /// <summary>
        /// 将呈现位块的数据给上下文.
        /// </summary>
        /// <param name="hdc">The HDC.</param>
        public override void Blit(IntPtr hdc)
        {
            if (deviceContextHandle != IntPtr.Zero || windowHandle != IntPtr.Zero)
            {
                //	Swap the buffers.
                Win32.SwapBuffers(deviceContextHandle);
            }
        }

        /// <summary>
        ///  确定渲染当前上下文
        /// </summary>
        public override void MakeCurrent()
        {
            if (renderContextHandle != IntPtr.Zero)
                Win32.wglMakeCurrent(deviceContextHandle, renderContextHandle);
        }
        
        #endregion
    }
}
